package com.rickpan.service.impl;

import com.rickpan.entity.Team;
import com.rickpan.entity.TeamInviteCode;
import com.rickpan.entity.TeamMember;
import com.rickpan.repository.TeamInviteCodeRepository;
import com.rickpan.service.TeamInviteCodeService;
import com.rickpan.service.TeamService;
import com.rickpan.service.TeamMemberService;
import com.rickpan.service.PermissionService;
import com.rickpan.util.ShareCodeGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

/**
 * 团队邀请码服务实现类
 */
@Service
@Transactional
public class TeamInviteCodeServiceImpl implements TeamInviteCodeService {

    private static final Logger logger = LoggerFactory.getLogger(TeamInviteCodeServiceImpl.class);

    @Autowired
    private TeamInviteCodeRepository inviteCodeRepository;

    @Autowired
    private TeamService teamService;

    @Autowired
    private TeamMemberService teamMemberService;

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private ShareCodeGenerator shareCodeGenerator;

    @Override
    public TeamInviteCode generateInviteCode(Long teamId, Long creatorId, TeamMember.Role inviteRole) {
        return generateInviteCode(teamId, creatorId, inviteRole, null, null);
    }

    @Override
    public TeamInviteCode generateInviteCode(Long teamId, Long creatorId, TeamMember.Role inviteRole, 
                                           LocalDateTime expireTime) {
        return generateInviteCode(teamId, creatorId, inviteRole, expireTime, null);
    }

    @Override
    public TeamInviteCode generateInviteCode(Long teamId, Long creatorId, TeamMember.Role inviteRole, 
                                           Integer maxUses) {
        return generateInviteCode(teamId, creatorId, inviteRole, null, maxUses);
    }

    @Override
    public TeamInviteCode generateInviteCode(Long teamId, Long creatorId, TeamMember.Role inviteRole, 
                                           LocalDateTime expireTime, Integer maxUses) {
        logger.info("生成团队邀请码 teamId={}, creatorId={}, role={}", teamId, creatorId, inviteRole);

        // 验证团队是否存在
        if (!teamService.existsById(teamId)) {
            throw new RuntimeException("团队不存在: " + teamId);
        }

        // 验证创建者是否为团队管理员
        if (!teamMemberService.isTeamAdmin(teamId, creatorId)) {
            throw new RuntimeException("只有团队管理员可以生成邀请码");
        }

        // 生成唯一邀请码
        String inviteCode = generateUniqueInviteCode();

        // 创建邀请码实体
        TeamInviteCode teamInviteCode = new TeamInviteCode(teamId, inviteCode, creatorId);
        teamInviteCode.setInviteRole(inviteRole);
        teamInviteCode.setExpireTime(expireTime);
        teamInviteCode.setMaxUses(maxUses);

        TeamInviteCode saved = inviteCodeRepository.save(teamInviteCode);
        logger.info("团队邀请码生成成功 id={}, code={}", saved.getId(), saved.getInviteCode());
        
        return saved;
    }

    @Override
    public TeamMember joinTeamByInviteCode(String inviteCode, Long userId) {
        logger.info("通过邀请码加入团队 inviteCode={}, userId={}", inviteCode, userId);

        // 查找并验证邀请码
        Optional<TeamInviteCode> inviteCodeOpt = inviteCodeRepository.findValidByInviteCode(
            inviteCode, LocalDateTime.now());
        
        if (!inviteCodeOpt.isPresent()) {
            throw new RuntimeException("邀请码无效或已过期");
        }

        TeamInviteCode teamInviteCode = inviteCodeOpt.get();
        Long teamId = teamInviteCode.getTeamId();

        // 检查用户是否已是团队成员
        if (teamMemberService.isTeamMember(teamId, userId)) {
            throw new RuntimeException("用户已是团队成员");
        }

        // 检查团队是否已满
        Optional<Team> teamOpt = teamService.findById(teamId);
        if (teamOpt.isPresent()) {
            Team team = teamOpt.get();
            if (team.getCurrentMembers() >= team.getMaxMembers()) {
                throw new RuntimeException("团队已满，无法加入");
            }
        }

        // 添加用户到团队
        TeamMember newMember = new TeamMember();
        newMember.setTeamId(teamId);
        newMember.setUserId(userId);
        newMember.setRole(teamInviteCode.getInviteRole());
        newMember.setStatus(TeamMember.Status.ACTIVE);

        TeamMember savedMember = teamMemberService.addMember(newMember);

        // 更新邀请码使用次数
        teamInviteCode.incrementUsedCount();
        inviteCodeRepository.save(teamInviteCode);

        logger.info("用户成功通过邀请码加入团队 userId={}, teamId={}", userId, teamId);
        return savedMember;
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<TeamInviteCode> findByInviteCode(String inviteCode) {
        return inviteCodeRepository.findByInviteCode(inviteCode);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean isValidInviteCode(String inviteCode) {
        Optional<TeamInviteCode> inviteCodeOpt = inviteCodeRepository.findValidByInviteCode(
            inviteCode, LocalDateTime.now());
        return inviteCodeOpt.isPresent() && inviteCodeOpt.get().isValid();
    }

    @Override
    @Transactional(readOnly = true)
    public List<TeamInviteCode> getTeamInviteCodes(Long teamId) {
        return inviteCodeRepository.findByTeamId(teamId);
    }

    @Override
    @Transactional(readOnly = true)
    public List<TeamInviteCode> getActiveInviteCodes(Long teamId) {
        return inviteCodeRepository.findActiveByTeamId(teamId);
    }

    @Override
    @Transactional(readOnly = true)
    public Page<TeamInviteCode> getTeamInviteCodes(Long teamId, Pageable pageable) {
        return inviteCodeRepository.findByTeamId(teamId, pageable);
    }

    @Override
    public void disableInviteCode(Long inviteCodeId, Long operatorId) {
        logger.info("禁用邀请码 id={}, operatorId={}", inviteCodeId, operatorId);

        Optional<TeamInviteCode> inviteCodeOpt = inviteCodeRepository.findById(inviteCodeId);
        if (!inviteCodeOpt.isPresent()) {
            throw new RuntimeException("邀请码不存在: " + inviteCodeId);
        }

        TeamInviteCode inviteCode = inviteCodeOpt.get();

        // 验证操作权限
        if (!teamMemberService.isTeamAdmin(inviteCode.getTeamId(), operatorId)) {
            throw new RuntimeException("只有团队管理员可以禁用邀请码");
        }

        inviteCode.setStatus(TeamInviteCode.Status.DISABLED);
        inviteCode.setUpdatedAt(LocalDateTime.now());
        inviteCodeRepository.save(inviteCode);

        logger.info("邀请码禁用成功 id={}", inviteCodeId);
    }

    @Override
    public void disableInviteCode(String inviteCode, Long operatorId) {
        Optional<TeamInviteCode> inviteCodeOpt = inviteCodeRepository.findByInviteCode(inviteCode);
        if (inviteCodeOpt.isPresent()) {
            disableInviteCode(inviteCodeOpt.get().getId(), operatorId);
        } else {
            throw new RuntimeException("邀请码不存在: " + inviteCode);
        }
    }

    @Override
    public void deleteInviteCode(Long inviteCodeId, Long operatorId) {
        logger.info("删除邀请码 id={}, operatorId={}", inviteCodeId, operatorId);

        Optional<TeamInviteCode> inviteCodeOpt = inviteCodeRepository.findById(inviteCodeId);
        if (!inviteCodeOpt.isPresent()) {
            throw new RuntimeException("邀请码不存在: " + inviteCodeId);
        }

        TeamInviteCode inviteCode = inviteCodeOpt.get();

        // 验证操作权限
        if (!teamMemberService.isTeamAdmin(inviteCode.getTeamId(), operatorId)) {
            throw new RuntimeException("只有团队管理员可以删除邀请码");
        }

        inviteCodeRepository.delete(inviteCode);
        logger.info("邀请码删除成功 id={}", inviteCodeId);
    }

    @Override
    public TeamInviteCode updateInviteCode(TeamInviteCode inviteCode) {
        logger.info("更新邀请码 id={}", inviteCode.getId());
        
        inviteCode.setUpdatedAt(LocalDateTime.now());
        return inviteCodeRepository.save(inviteCode);
    }

    @Override
    public TeamInviteCode refreshInviteCode(Long inviteCodeId, Long operatorId) {
        logger.info("刷新邀请码 id={}, operatorId={}", inviteCodeId, operatorId);

        Optional<TeamInviteCode> inviteCodeOpt = inviteCodeRepository.findById(inviteCodeId);
        if (!inviteCodeOpt.isPresent()) {
            throw new RuntimeException("邀请码不存在: " + inviteCodeId);
        }

        TeamInviteCode inviteCode = inviteCodeOpt.get();

        // 验证操作权限
        if (!teamMemberService.isTeamAdmin(inviteCode.getTeamId(), operatorId)) {
            throw new RuntimeException("只有团队管理员可以刷新邀请码");
        }

        // 生成新的邀请码
        String newCode = generateUniqueInviteCode();
        inviteCode.setInviteCode(newCode);
        inviteCode.setUsedCount(0);
        inviteCode.setStatus(TeamInviteCode.Status.ACTIVE);
        inviteCode.setUpdatedAt(LocalDateTime.now());

        TeamInviteCode updated = inviteCodeRepository.save(inviteCode);
        logger.info("邀请码刷新成功 id={}, newCode={}", inviteCodeId, newCode);
        
        return updated;
    }

    // 私有辅助方法

    @Override
    @Transactional(readOnly = true)
    public InviteCodeStats getInviteCodeStats(Long teamId) {
        logger.debug("获取团队邀请码统计 teamId={}", teamId);

        List<TeamInviteCode> allCodes = inviteCodeRepository.findByTeamId(teamId);

        long totalCodes = allCodes.size();
        long activeCodes = allCodes.stream().mapToLong(code ->
            code.getStatus() == TeamInviteCode.Status.ACTIVE ? 1 : 0).sum();
        long expiredCodes = allCodes.stream().mapToLong(code ->
            code.getStatus() == TeamInviteCode.Status.EXPIRED ? 1 : 0).sum();
        long exhaustedCodes = allCodes.stream().mapToLong(code ->
            code.getStatus() == TeamInviteCode.Status.EXHAUSTED ? 1 : 0).sum();
        long disabledCodes = allCodes.stream().mapToLong(code ->
            code.getStatus() == TeamInviteCode.Status.DISABLED ? 1 : 0).sum();
        long totalUses = allCodes.stream().mapToLong(TeamInviteCode::getUsedCount).sum();

        return new InviteCodeStats(totalCodes, activeCodes, expiredCodes,
                                  exhaustedCodes, disabledCodes, totalUses);
    }

    @Override
    public int cleanupExpiredCodes() {
        logger.info("清理过期的邀请码");
        return inviteCodeRepository.updateExpiredCodes(LocalDateTime.now());
    }

    @Override
    public int cleanupExhaustedCodes() {
        logger.info("清理用完的邀请码");
        return inviteCodeRepository.updateExhaustedCodes(LocalDateTime.now());
    }

    @Override
    @Transactional(readOnly = true)
    public List<TeamInviteCode> getUserInviteCodes(Long userId) {
        return inviteCodeRepository.findByCreatorId(userId);
    }

    @Override
    @Transactional(readOnly = true)
    public boolean canCreateInviteCode(Long userId, Long teamId) {
        // 检查用户是否为团队管理员
        if (!teamMemberService.isTeamAdmin(teamId, userId)) {
            return false;
        }

        // 检查团队活跃邀请码数量限制（最多10个）
        long activeCount = inviteCodeRepository.countActiveByTeamId(teamId);
        return activeCount < 10;
    }

    @Override
    @Transactional(readOnly = true)
    public List<TeamInviteCode> getExpiringSoonCodes(Long teamId) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime expireSoon = now.plusDays(1); // 24小时内过期
        return inviteCodeRepository.findExpiringSoon(now, expireSoon);
    }

    // 私有辅助方法

    /**
     * 生成唯一邀请码
     */
    private String generateUniqueInviteCode() {
        String inviteCode;
        int attempts = 0;

        do {
            inviteCode = shareCodeGenerator.generateShareCode(8);
            attempts++;
        } while (attempts < 10 && inviteCodeRepository.existsByInviteCode(inviteCode));

        if (attempts >= 10) {
            throw new RuntimeException("生成邀请码失败，请重试");
        }

        return inviteCode;
    }
}
